package lj.netty.tool;

import cn.hutool.core.map.BiMap;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.log.StaticLog;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;

import java.util.HashMap;

/**
 * netty 操作工具类
 */
public class LJTNetty {

    /** 所有通道容器 */
    public static ChannelGroup GlobalGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    /** 通道绑定唯一标识 */
    public static final BiMap<String, ChannelId> channelIdMap = new BiMap<>(new HashMap<>());

    /**
     * 添加channel到容器
     * @param channel
     */
    public static void addChannel(Channel channel) {
        ChannelId id = channel.id();
        channelIdMap.put(id.asLongText(), id);
        GlobalGroup.add(channel);
    }

    /**
     * 获取 channel
     * @param target
     * @return
     */
    public static Channel getChannel(String target) {
        ChannelId channelId = channelIdMap.get(target);
        if (ObjectUtil.isNull(channelId)) {
            return null;
        }
        Channel channel = GlobalGroup.find(channelId);
        if (channel == null || !channel.isOpen() || !channel.isActive()) {
            removeChannel(channel);
            return null;
        }
        return channel;
    }

    /**
     * 推送消息
     * @param target
     * @param bytes
     * @return
     */
    public static boolean push(String target, byte[] bytes) {
        Channel channel = getChannel(target);
        if (ObjectUtil.isNull(channel)) {
            return false;
        }
//        StaticLog.info("发送[{}]数据[{}]", target, JSONUtil.toJsonStr(ArrayUtil.sub(bytes, 0, 200)));
        channel.writeAndFlush(Unpooled.wrappedBuffer(bytes));
        return true;
    }

    /**
     * 推送所有人消息
     * @param bytes
     * @return
     */
    public static void pushAll(byte[] bytes) {
        ByteBuf byteBuf = Unpooled.wrappedBuffer(bytes);
        channelIdMap.forEach((k, v) -> {
            Channel channel = GlobalGroup.find(v);
            if (channel != null && channel.isOpen() && channel.isActive()) {
                channel.writeAndFlush(byteBuf);
//                StaticLog.info("发送[{}]数据[{}]", "*", JSONUtil.toJsonStr(ArrayUtil.sub(bytes, 0, 200)));
            }
        });
    }

    /**
     * 删除通道
     * @param channel
     */
    public static void removeChannel(Channel channel) {
        if (ObjectUtil.isNull(channel)) {
            return;
        }
        GlobalGroup.remove(channel);
        if (channelIdMap.containsValue(channel.id())) {
            channelIdMap.getInverse().remove(channel.id());
        }
    }

}
